import logging

from flask_restful import Resource
from flask import g, Response
from framework.util.ComplexEncoder import ComplexEncoder
from framework.util.DatetimeUtil import DatetimeUtil
from framework.util.DbUtil import DbUtil
from framework.util.RespUtil import RespUtil
from framework.vo.RespResult import RespResult
from framework.constant.RequestMethod import RequestMethod
import traceback
import json
from jsonschema.exceptions import ValidationError

class AbstractApi(Resource):
    """
    API抽象类，所有api都应继承此类
    """

    def __init__(self):
        self.db = DbUtil()
        self.dt_util = DatetimeUtil()

    def get(self):
        return self.__handle_and_resp(RequestMethod.GET)

    def post(self):
        return self.__handle_and_resp(RequestMethod.POST)

    def __handle_and_resp(self, method: RequestMethod):

        try:
            if method == RequestMethod.POST:
                result = self.handle_post_request()
                if result is None:
                    result = {}
            else:
                result = self.handle_get_request()

            if isinstance(result, RespResult):
                return result.build()

            if isinstance(result, Response):
                return result
            return RespUtil.ok(json.loads(json.dumps(result, cls=ComplexEncoder))).build()
        except ValidationError as e:
            logging.error("参数验证异常", exc_info=True)
            return  RespUtil.param_lack(e.args[0]).build()
        except Exception as e:
            logging.error("内部异常", exc_info=True)
            return RespUtil.inner_error(e.args[0]).build()


    def handle_get_request(self):
        return RespUtil.request_method_invalid()

    def handle_post_request(self):
        return RespUtil.request_method_invalid()

    def get_param(self, field, default=None):
        if not hasattr(g, 'request_data'):
            return None

        params = dict(g.request_data)

        value = params.get(field, default)
        if value == '' or value is None:
            return None

        return value
